package com.syezon.wifikey.view;

import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.Typeface;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;

import com.syezon.wifikey.R;


public class RadarView extends View {

    public static final String DEFAULT_FORMAT = "%1$.0f";

    /**
     * 是否是扫描状态
     */
    private boolean mIsScaning = false;
    /**
     * 是否显示雷达界面（有雷达和分数两种界面效果）
     */
    private boolean mIsRadar = true;

    /**
     * 画笔
     */
    private Paint mPaint;

    /**
     * 内圆环笔画宽度
     */
    private float mInsideStrokeWidth;
    /**
     * 外圆环笔画宽度
     */
    private float mOutsideStrokeWidth;
    /**
     * 对角线笔画宽度
     */
    private float mLineStrokeWidth;

    /**
     * 圆心坐标
     */
    private float mCircleCenterX, mCircleCenterY;

    /**
     * 外圆半径
     */
    private float mRadius;

    /**
     * 内圆半径
     */
    private float mInsideRadius;
    /**
     * 雷达扫描圆环的颜色
     */
    private int mCircleColor = Color.parseColor("#52fff9");
    /**
     * 对角线的颜色
     */
    private int mLineColor = Color.parseColor("#1ecdf4");

    /**
     * 分数界面外边框的颜色
     */
    private int mSideColor = Color.parseColor("#52fff9");
    /**
     * 分数界面外圆环的颜色
     */
    private int mOutsideBackgroundColor = Color.parseColor("#1bb8f2");
    /**
     * 分数界面内圆环的颜色
     */
    private int mInsideBackgroundColor = Color.WHITE;

    /**
     * 分数文本颜色
     */
    private int mTextColor = Color.parseColor("#01b0f1");
    /**
     * 分数标签文本颜色
     */
    private int mLabelTextColor = Color.parseColor("#01b0f1");

    /**
     * 显示分数文本的字体大小
     */
    private float mTextSize;
    /**
     * 显示分数文本标签的字体大小
     */
    private float mLabelTextSize;

    /**
     * 用于绘制雷达圆环的着色器
     */
    private Shader mCircleShader;
    /**
     * 用于绘制雷达扫描区域的着色器
     */
    private Shader mScanShader;

    private Matrix mMatrix;

    /**
     * 雷达扫描旋转的角度
     */
    private int mRotate;

    /**
     * 是否显示对角线
     */
    private boolean mIsShowLine = false;

    /**
     * 文本里圆心的Y轴偏移量
     */
    private float mTextOffsetY;
    /**
     * 标签里圆心的Y轴偏移量
     */
    private float mLabelTextOffseY;

    private String mFormat = DEFAULT_FORMAT;

    private boolean mIsShowLabel = true;

    private boolean mIsShowText = true;

    /**
     * 是否显示动画(显示分数时)
     */
    private boolean mIsShowAnim = true;

    private String mLabelText;
    /**
     * 分数值
     */
    private float mValue;

    /**
     * 文本
     */
    private String mText;

    /**
     * 显示分数动画持续时间
     */
    private int mDuration = 500;

    /**
     * 扫描延迟时间（扫描旋转隔时间,默认2毫秒旋转一度）
     */
    private int mScanTime = 2;
    /**
     * 最后扫描刷新时间
     */
    private float mLastTime;

    public RadarView(Context context) {
        this(context, null);
    }

    public RadarView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RadarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public RadarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context, attrs);
    }


    private void init(Context context, AttributeSet attrs) {
        mPaint = new Paint();
        mMatrix = new Matrix();
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RadarView);

        mTextSize = a.getDimension(R.styleable.RadarView_android_textSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 40, getDisplayMetrics()));
        mTextColor = a.getColor(R.styleable.RadarView_android_textColor, mTextColor);
        mText = a.getString(R.styleable.RadarView_android_text);

        mLabelTextSize = a.getDimension(R.styleable.RadarView_labelTextSize, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, getDisplayMetrics()));
        mLabelTextColor = a.getColor(R.styleable.RadarView_labelTextColor, mTextColor);
        mLabelText = a.getString(R.styleable.RadarView_labelText);
        mFormat = a.getString(R.styleable.RadarView_format);
        if (TextUtils.isEmpty(mFormat)) {
            mFormat = DEFAULT_FORMAT;
        }

        mSideColor = a.getColor(R.styleable.RadarView_sideColor, mSideColor);
        mOutsideBackgroundColor = a.getColor(R.styleable.RadarView_outsideBackgroundColor, mOutsideBackgroundColor);
        mInsideBackgroundColor = a.getColor(R.styleable.RadarView_insideBackgroundColor, mInsideBackgroundColor);

        mDuration = a.getInt(R.styleable.RadarView_duration, mDuration);

        mTextOffsetY = a.getDimension(R.styleable.RadarView_textOffsetY, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getDisplayMetrics()));
        mLabelTextOffseY = a.getDimension(R.styleable.RadarView_labelTextOffsetY, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 36, getDisplayMetrics()));
        mCircleColor = a.getColor(R.styleable.RadarView_circleColor, mCircleColor);
        mLineColor = a.getColor(R.styleable.RadarView_lineColor, mLineColor);
        mRotate = a.getInt(R.styleable.RadarView_rotate, mRotate);
        mIsShowLine = a.getBoolean(R.styleable.RadarView_showLine, mIsShowLine);
        mIsShowText = a.getBoolean(R.styleable.RadarView_showText, mIsShowText);
        mIsShowLabel = a.getBoolean(R.styleable.RadarView_showLabel, mIsShowLabel);
        mScanTime = a.getInt(R.styleable.RadarView_scanTime, mScanTime);

        mInsideStrokeWidth = a.getDimension(R.styleable.RadarView_insideStrokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getDisplayMetrics()));
        mOutsideStrokeWidth = a.getDimension(R.styleable.RadarView_outsideStrokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, getDisplayMetrics()));
        mLineStrokeWidth = a.getDimension(R.styleable.RadarView_lineStrokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0.3f, getDisplayMetrics()));
        a.recycle();
    }


    private DisplayMetrics getDisplayMetrics() {
        return getResources().getDisplayMetrics();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //默认值
        int defaultValue = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200, getDisplayMetrics());
        //默认宽高
        int defaultWidth = defaultValue + getPaddingLeft() + getPaddingRight();
        int defaultHeight = defaultValue + getPaddingTop() + getPaddingBottom();

        int width = measureHandler(widthMeasureSpec, defaultWidth);
        int height = measureHandler(heightMeasureSpec, defaultHeight);

        //圆心坐标
        mCircleCenterX = (width + getPaddingLeft() - getPaddingRight()) / 2.0f;
        mCircleCenterY = (height + getPaddingTop() - getPaddingBottom()) / 2.0f;

        //外圆半径
        mRadius = (width - getPaddingLeft() - getPaddingRight() - mOutsideStrokeWidth) / 2.0f;
        //内院的半径 为外援半径的1/3
        mInsideRadius = mRadius / 3;

        setMeasuredDimension(width, height);

        setCircleColor(Color.parseColor("#00FFFFFF"), Color.parseColor("#3fFFFFFF"), Color.parseColor("#5fFFFFFF"), Color.parseColor("#FFFFFF"));
        setScanColor(Color.parseColor("#00FFFFFF"), Color.parseColor("#1fFFFFFF"), Color.parseColor("#2fFFFFFF"), Color.parseColor("#5fFFFFFF"));
    }


    private int measureHandler(int measureSpec, int defaultSize) {

        int result = defaultSize;
        int measureMode = MeasureSpec.getMode(measureSpec);
        int measureSize = MeasureSpec.getSize(measureSpec);
        if (measureMode == MeasureSpec.UNSPECIFIED) {
            result = defaultSize;
        } else if (measureMode == MeasureSpec.AT_MOST) {
            result = Math.min(defaultSize, measureSize);
        } else {
            result = measureSize;
        }
        return result;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mIsRadar) {
            drawRadar(canvas);
        } else {
            drawScore(canvas);
        }
    }

    /**
     * 绘制雷达扫描图
     *
     * @param canvas
     */
    private void drawRadar(Canvas canvas) {
        mPaint.reset();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);

        canvas.save();
        canvas.rotate(mRotate, mCircleCenterX, mCircleCenterY);
        mMatrix.setRotate(mRotate, mCircleCenterX, mCircleCenterY);
        mPaint.setColor(mLineColor);
        mPaint.setStrokeWidth(mLineStrokeWidth);
        canvas.drawLine(mCircleCenterX, mCircleCenterY, mCircleCenterX + mRadius + mOutsideStrokeWidth / 2, mCircleCenterY, mPaint);
        canvas.restore();

        //绘制圆环的渐变着色器
        if (mCircleShader == null) {
            mCircleShader = new SweepGradient(mCircleCenterX, mCircleCenterY, Color.TRANSPARENT, mCircleColor);
        }
        mCircleShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mCircleShader);

        mPaint.setStrokeWidth(mInsideStrokeWidth);
        mPaint.setColor(mCircleColor);
        //绘制内框圆
//        canvas.drawCircle(mCircleCenterX,mCircleCenterY,mInsideRadius,mPaint);
//        canvas.drawCircle(mCircleCenterX,mCircleCenterY,mInsideRadius * 2,mPaint);

        //绘制外框圆
        mPaint.setStrokeWidth(mOutsideStrokeWidth);
        canvas.drawCircle(mCircleCenterX, mCircleCenterY, mRadius, mPaint);

        //绘制圆扫描区域的渐变着色器
        if (mScanShader == null) {
            mScanShader = new SweepGradient(mCircleCenterX, mCircleCenterY, new int[]{Color.TRANSPARENT, Color.TRANSPARENT, mCircleColor}, null);
        }
        mScanShader.setLocalMatrix(mMatrix);
        mPaint.setShader(mScanShader);
        mPaint.setStyle(Paint.Style.FILL);

        //绘制扫面区域
        float radius = mRadius + mOutsideStrokeWidth / 2;
        canvas.drawCircle(mCircleCenterX, mCircleCenterX, radius, mPaint);
    }


    /**
     * 绘制扫描结果分数图
     *
     * @param canvas
     */
    private void drawScore(Canvas canvas) {
        mPaint.reset();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setStrokeWidth(mInsideStrokeWidth);
        mPaint.setColor(mSideColor);

        //绘制外框圆
        canvas.drawCircle(mCircleCenterX, mCircleCenterY, mRadius, mPaint);

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mOutsideBackgroundColor);
        canvas.drawCircle(mCircleCenterX, mCircleCenterY, mRadius, mPaint);

        //绘制内框圆
        mPaint.setColor(mInsideBackgroundColor);
        canvas.drawCircle(mCircleCenterX, mCircleCenterY, mInsideRadius * 2, mPaint);

        mPaint.setTypeface(Typeface.DEFAULT);
        mPaint.setTextAlign(Paint.Align.CENTER);

        if (mIsShowLabel && !TextUtils.isEmpty(mLabelText)) {//绘制标签文本逻辑
            mPaint.setColor(mLabelTextColor);
            mPaint.setTextSize(mLabelTextSize);
            float x = mCircleCenterX;
            float y = mCircleCenterY + mLabelTextOffseY;
            canvas.drawText(mLabelText, x, y, mPaint);
        }

        if (mIsShowText && !TextUtils.isEmpty(mText)) {//绘制文本逻辑
            mPaint.setColor(mTextColor);
            mPaint.setTextSize(mTextSize);
            mPaint.setFakeBoldText(true);
            float x = mCircleCenterX;
            float y = mCircleCenterY + mTextOffsetY;
            canvas.drawText(mText, x, y, mPaint);
        }

    }

    private String getFormatText(float value, String format) {
        if (TextUtils.isEmpty(format)) {
            return String.valueOf(value);
        }
        return String.format(format, value);
    }

    public void showText(String text) {
        mIsRadar = false;
        setText(text);
    }

    /**
     * 显示分数
     *
     * @param value 目标值（最终分数）
     */
    public void showScore(float value) {
        showScore(value, mDuration);
    }

    /**
     * 显示分数
     *
     * @param value    目标值（最终分数）
     * @param duration 从初始值到目标值的动画持续时间
     */
    public void showScore(float value, int duration) {
        showScore(0, value, duration);
    }

    /**
     * 显示分数
     *
     * @param from     初始值
     * @param to       目标值（最终分数）
     * @param duration 从初始值到目标值的动画持续时间
     */
    public void showScore(float from, float to, int duration) {
        showScore(from, to, duration, mIsShowAnim);
    }

    /**
     * 显示分数
     *
     * @param from       初始值
     * @param to         目标值（最终分数）
     * @param duration   从初始值到目标值的动画持续时间
     * @param isShowAnim 是否显示动画
     */
    public void showScore(float from, float to, int duration, boolean isShowAnim) {
        showScore(from, to, duration, mFormat, isShowAnim);
    }

    /**
     * 显示分数
     *
     * @param from       初始值
     * @param to         目标值（最终分数）
     * @param duration   从初始值到目标值的动画持续时间
     * @param format
     * @param isShowAnim 是否显示动画
     */
    public void showScore(float from, float to, int duration, final String format, boolean isShowAnim) {
        this.mIsRadar = false;
        this.mDuration = duration;
        this.mFormat = (format == null ? DEFAULT_FORMAT : format);
        this.mIsShowAnim = isShowAnim;
        if (mIsShowAnim) {
            ValueAnimator valueAnimator = ValueAnimator.ofFloat(from, to);
            valueAnimator.setDuration(duration);
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mValue = (float) animation.getAnimatedValue();
                    setText(mValue, format);
                }
            });

            valueAnimator.start();
        } else {
            mValue = to;
            setText(mValue, format);
        }

    }


    public void setText(@StringRes int resId) {
        this.mText = getResources().getString(resId);
        if (!mIsRadar) {
            invalidate();
        }
    }

    public void setText(String text) {
        this.mText = text;
        if (!mIsRadar) {
            invalidate();
        }
    }

    /**
     * 设置分数文本
     *
     * @param value
     * @param format
     */
    public void setText(float value, String format) {
        this.mValue = value;
        this.mFormat = (TextUtils.isEmpty(format) ? DEFAULT_FORMAT : format);
        this.mText = getFormatText(value, format);
        if (!mIsRadar) {
            invalidate();
        }
    }

    public void setLabelText(@StringRes int resId) {
        this.mLabelText = getResources().getString(resId);
        if (!mIsRadar) {
            invalidate();
        }
    }

    public void setLabelText(String text) {
        this.mLabelText = text;
        if (!mIsRadar) {
            invalidate();
        }
    }

    /**
     * 开始扫描动画
     */
    public void start() {
        mIsRadar = true;
        mIsScaning = true;
        updateScan();
    }

    public void start(int... colors) {
        setScanColor(colors);
        start();
    }

    /**
     * 更新雷达扫描区域
     */
    private void updateScan() {
        float curTime = System.currentTimeMillis();
        if (curTime >= mLastTime + mScanTime && mIsScaning) {
            mLastTime = curTime;
            removeCallbacks(mRunnable);
            postDelayed(mRunnable, mScanTime);
        }

    }

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            mRotate = mRotate + 2;
            if (mRotate >= 360) {
                mRotate = 0;
            }
            invalidate();
            updateScan();
        }
    };

    /**
     * 停止扫描动画
     */
    public void stop() {
        mIsScaning = false;
        mRotate = 0;
        invalidate();
    }

    public void setInsideStrokeWidth(float insideStrokeWidth) {
        this.mInsideStrokeWidth = insideStrokeWidth;
    }

    public void setOutsideStrokeWidth(float outsideStrokeWidth) {
        this.mOutsideStrokeWidth = outsideStrokeWidth;
    }

    public void setLineStrokeWidth(float lineStrokeWidth) {
        this.mLineStrokeWidth = lineStrokeWidth;
    }

    public void setCircleColor(int circleColor) {
        this.mCircleColor = circleColor;
    }

    public void setLineColor(int lineColor) {
        this.mLineColor = lineColor;
    }

    public void setSideColor(int sideColor) {
        this.mSideColor = sideColor;
    }

    public void setOutsideColor(int outsideColor) {
        this.mOutsideBackgroundColor = outsideColor;
    }

    public void setInsideColor(int insideColor) {
        this.mInsideBackgroundColor = insideColor;
    }

    public void setTextColor(int textColor) {
        this.mTextColor = textColor;
    }

    public void setLabelTextColor(int labelTextColor) {
        this.mLabelTextColor = labelTextColor;
    }

    public void setTextSize(float textSize) {
        this.mTextSize = textSize;
    }

    public void setLabelTextSize(float labelTextSize) {
        this.mLabelTextSize = labelTextSize;
    }

    public void setRotate(int rotate) {
        this.mRotate = rotate;
    }

    public void setShowLine(boolean isShowLine) {
        this.mIsShowLine = isShowLine;
    }

    public void setTextOffsetY(float textOffsetY) {
        this.mTextOffsetY = textOffsetY;
    }

    public void setShowLabel(boolean showLabel) {
        mIsShowLabel = showLabel;
    }

    public void setShowText(boolean showText) {
        mIsShowText = showText;
    }

    public void setShowAnim(boolean isShowAnim) {
        this.mIsShowAnim = isShowAnim;
    }

    public void setDuration(int duration) {
        this.mDuration = duration;
    }

    public void setScanTime(int scanTime) {
        this.mScanTime = scanTime;
    }

    public boolean isRadar() {
        return mIsRadar;
    }

    public int getCircleColor() {
        return mCircleColor;
    }

    public int getLineColor() {
        return mLineColor;
    }

    public int getSideColor() {
        return mSideColor;
    }

    public int getOutsideColor() {
        return mOutsideBackgroundColor;
    }

    public void setRadar(boolean isRadar) {
        this.mIsRadar = isRadar;
    }

    public int getInsideColor() {
        return mInsideBackgroundColor;
    }

    public int getTextColor() {
        return mTextColor;
    }

    public int getLabelTextColor() {
        return mLabelTextColor;
    }

    /**
     * 雷达扫描区域的着色器色值
     *
     * @param colors 传多个色值表示渐变
     */
    public void setScanColor(int... colors) {
        mScanShader = new SweepGradient(mCircleCenterX, mCircleCenterY, colors, null);
    }

    /**
     * 雷达内外圆环的着色器色值
     *
     * @param colors 传多个色值表示渐变
     */
    public void setCircleColor(int... colors) {
        mCircleShader = new SweepGradient(mCircleCenterX, mCircleCenterY, colors, null);
    }
}
